#!/usr/bin/env python
# vim:fileencoding=utf-8 shiftwidth=2 tabstop=2 expandtab

"""  CEDU TD3 - Google App Engine

User sign-in and personalization for TD3 project web services,
plus Education Data Warehouse reporting pipeline.

Created by and copyright 2009, 2010 
CEDU, the Center for Education Data Use, 
Hampshire Educational Collaborative,
Northampton, Massachusetts.

"""

import os
import re
import httplib
import urllib
import urllib2
import cgi
import logging

from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


# Decide whether to use the real ceduauth or a local test version.
if 0:  # os.environ['SERVER_SOFTWARE'][:11] == 'Development', but we want to choose manually
  MEMBERSHIP_URL = 'http://localhost:8080/member/'
else:
  MEMBERSHIP_URL = 'https://ceduauth.appspot.com/member/'

GROUP = 'groups.google.com/group/cedu-td3'


class UserState(webapp.RequestHandler):
  """  HTML indicating whether a user is signed in.
  """

  def get(self):
    self.response.out.write('<html><body>')
    user = users.get_current_user()
    if user:
      self.response.out.write(user.email() + ' signed in.')
    else:
      self.response.out.write('Not signed in.')
    self.response.out.write('</body></html>')
    # Indicate this output expires on delivery.
    self.response.headers['Expires'] = '0'


class UserEntry(webapp.RequestHandler):
  """  Main user entry / sign-in handler

  Sign in to the TD3 project and display your personal project page.

  This involves signing in to this application, so we know who you are,
    signing in to Google Sites, so you can be authorized,
    and maybe signing in to other Google services.

  Most project members are authorized for the site and documents indirectly 
    as members of the TD3 Google Group, cedu-td3@googlegroups.com.
  """

  def get(self):
    # If a 'new' parameter is supplied, sign out before signing in.
    if self.request.get('new'):
      self.redirect(users.create_logout_url(self.request.url))
      return

    user = users.get_current_user()

    # If you are not signed in, do so at Google Accounts then return here.
    # [First check against our list of known email addresses and first-timers.]
    if not user:
      self.redirect(users.create_login_url(self.request.uri))
      return

    # You are signed in.
    # Let's find out if you're a member.
    email = user.email()
    logging.info('%s signing in', email)
    try:
      query_member = urllib2.urlopen(MEMBERSHIP_URL + GROUP, urllib.urlencode({'email' : email}))
    except urllib2.URLError, error:
      logging.error('Membership check HTTP error: %s', str(error))
      if isinstance(error, urllib2.HTTPError):
        query_member = error  # error response from host
      else:
        self.response.out.write('<html><body><h1>Membership system problem</h1>')
        self.response.out.write('<p>The TD3 membership system returned a strange error when')
        self.response.out.write('we requested a membership check for ' + email + ':</p>')
        self.response.out.write('<code>' + str(error.reason) + '</code></body></html>')
        return
    response_line = query_member.read()
    if not response_line:  # not a member
      logging.info('%s not a member', email)
      self.unauthorized_email(email)
      return
    email = response_line;
    # Looks good. 
    logging.info('Member %s signed in', email)
    # Do you have a user page?
    user_page = re.sub(r'[^a-z0-9]', '-', email.lower())
    site_path = '/site/cedutd3'
    user_path = site_path + '/user/' + user_page
    host = 'sites.google.com'
    user_page_url = "http://" + host + user_path
    home_page_url = "http://" + host + site_path
    self.response.out.write("<br/>" + user_path)
    sites_connection = httplib.HTTPConnection('sites.google.com')
    sites_connection.request("HEAD", user_path)
    sites_response = sites_connection.getresponse()
    if sites_response.status == 200:  # page is OK
      goto = user_page_url
    else:  # assume user page doesn't exist.
      goto = home_page_url
      logging.warning('Status %d returned when checking user page at %s', sites_response.status, user_page_url)
    # Route user through Sites sign-in, usually transparently.
    sites_sign_in = "https://www.google.com/accounts/ServiceLogin?service=jotspot&passive=true&ul=1"
    self.redirect(sites_sign_in + "&continue=" + urllib.quote(goto, ''))

  def unauthorized_email(self, email):
    self.response.out.write('''<html><head><title>Unauthorized email address</title></head>
    <body><h1>Your email address...</h1>
    <p>You are signed in to Google and the TD3 project using email address &lt;'''
    + email + '''>, <br/>but I can't find that email address in the TD3 member list.
    </p><p>
    <a href="''' + self.request.url + '''?new=yes">Sign in using a different email address</a>
    </p>
    </body></html>''')


class SignOut(webapp.RequestHandler):
  def get(self):
    self.redirect(users.create_logout_url("http://sites.google.com/site/cedutd3"))


class WhoAmI(webapp.RequestHandler):
  'Respond with signed-in email address or blank.'

  def get(self):
    user = users.get_current_user()
    if user:
      self.response.out.write(user.email())
    else:
      self.response.clear()

class Data(webapp.RequestHandler):

  def get(self):
    self.response.out.write('<html><head><title>fetch</title></head><body>')
    self.response.out.write('\n<button onclick="fetch()">fetch</button>')
    self.response.out.write('\n<button onclick="peek()">peek</button>')
    self.response.out.write('''<script type="text/javascript">
      function fetch() {
        alert("arf!");
      }
      function peek() {
        alert("I see you!");
      }
    </script>''')
    self.response.out.write('''<form action="/data" method="post">
    <input type="submit" value="Submit" />
    <textarea name="data" rows="10" cols="80" />
    </form>''')
    self.response.out.write('\n</body></html>\n')
  def post(self):
    self.response.out.write('<html><body>')
    storage = ReceivedData.all().fetch(1)
    if len(storage) > 0:
      storage = storage[0]
      self.response.out.write('Using existing storage.<br/>')
    else:
      storage = ReceivedData()
      self.response.out.write('Creating new storage.<br/>')
    storage.data = self.request.body
    self.response.out.write('Body: ' + str(len(storage.data)) + ' characters.<br/>')
    if len(storage.data) == 0:
      storage.data = self.request.get("data")
      self.response.out.write('data parameter: ' + str(len(storage.data)) + ' characters.<br/>')
    self.response.out.write('Storage key: ' + str(storage.put()))
    self.response.out.write('</body></html>')

class ReceivedData(db.Model):
  data = db.TextProperty()


application = webapp.WSGIApplication([('/', UserEntry), 
                                      ('/sign-in', UserEntry),
                                      ('/sign-out', SignOut),
                                      ('/whoami', WhoAmI),   
                                      ('/userstate.html', UserState),
                                      ('/data', Data),
				     ],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()
